package cn.xyz.repository.mongo;

import cn.xyz.commons.support.mongo.MongoOperator;
import cn.xyz.commons.utils.DateUtil;
import cn.xyz.commons.utils.DocumentToJavaBean;
import cn.xyz.commons.utils.StringUtil;
import cn.xyz.mianshi.model.PageResult;
import cn.xyz.mianshi.model.PageVO;
import cn.xyz.mianshi.service.impl.FriendsManagerImpl;
import cn.xyz.mianshi.utils.SKBeanUtils;
import cn.xyz.mianshi.vo.Friends;
import cn.xyz.mianshi.vo.Role;
import cn.xyz.repository.FriendsRepository;
import com.google.common.collect.Lists;
import com.mongodb.DBObject;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.query.Query;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
@Service
public class FriendsRepositoryImpl extends MongoRepository<Friends, ObjectId> implements FriendsRepository {

	@Override
	public Class<Friends> getEntityClass() {
		// TODO Auto-generated method stub
		return Friends.class;
	}
	@Override
	public Datastore getDatastore() {
		return SKBeanUtils.getDatastore();
	}



	private static FriendsManagerImpl getFriendsManagerImpl(){
		return SKBeanUtils.getFriendsManager();
	}
	
	/** Friends Collection
	 * @param userId
	 * @return
	 */
	private MongoCollection<DBObject> getFriendsMongoCollection(int userId){
		return getFriendsManagerImpl().getDBObjectCollection(userId);
	}



	@Override
	public void deleteFriends(int userId) {
		/**
		 * 分库分表下删除好友相关数据
		 */
		getFriendsMongoCollection(userId).deleteMany(new Document("userId",userId));
	}
	

	@Override
	public void deleteFriends(int userId, int toUserId) {

		/**
		 * 分库分表下的好友、粉丝数据删除
		 */
		getFriendsMongoCollection(userId).deleteOne(new Document("userId",userId).append("toUserId", toUserId));

	}
	
	@Override
	public Friends getFriends(int userId, int toUserId) {

		/**
		 * 分库分表下的friends数据
		 */
		MongoCollection<DBObject> userCollection = getFriendsMongoCollection(userId);
		DBObject first = userCollection.find(new Document("userId",userId).append("toUserId", toUserId)).first();
		if(null==first)
			return null;
		Friends userfriends = null;

			try {
				 userfriends = DocumentToJavaBean.dbObject2Bean(first, new Friends());
			} catch (IllegalAccessException | InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		MongoCollection<DBObject> toUserCollection = getFriendsMongoCollection(toUserId);
		first=toUserCollection.find(new Document("userId", toUserId).append("toUserId", userId)).first();
		if(null!=first) {
			Friends toUserfriends = null;
			try {
				toUserfriends = DocumentToJavaBean.dbObject2Bean(first, new Friends());
			} catch (IllegalAccessException | InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (null == userfriends)
				return userfriends;
			else if (null == toUserfriends)
				userfriends.setIsBeenBlack(0);
			else
				userfriends.setIsBeenBlack(toUserfriends.getBlacklist());
		}

		return userfriends;
	}

	@SuppressWarnings("deprecation")
	@Override
	public List<Friends> queryBlacklist(int userId,int pageIndex,int pageSize) {
		/**
		 * 分库分表下的friends数据
		 */
		List<Friends> friendList = new ArrayList<Friends>();
		MongoCursor<DBObject> iterator = getFriendsMongoCollection(userId).find(new Document("userId",userId).append("blacklist", 1)).skip(pageIndex*pageSize).limit(pageSize).iterator();
		while(iterator.hasNext()){
			DBObject dbObject = iterator.next();
			 try {
				 Friends friends =	DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
				 if(null!=friends)
					 friendList.add(friends);
			} catch (IllegalAccessException | InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return friendList;
	}
	
	@SuppressWarnings("deprecation")
	public PageVO queryBlacklistWeb(int userId,int pageIndex,int pageSize)  {
		/**
		 * 分库分表下的friends数据
		 */
		List<Friends> friendList = new ArrayList<Friends>();
		MongoCollection<DBObject> friendsCollection = getFriendsMongoCollection(userId);
		long count = friendsCollection.count(new Document("userId",userId).append("blacklist", 1));
		MongoCursor<DBObject> iterator = friendsCollection.find(new Document("userId",userId).append("blacklist", 1)).skip(pageIndex*pageSize).limit(pageSize).iterator();
		while(iterator.hasNext()){
			DBObject dbObject = iterator.next();
			Friends friends;
			try {
				friends = DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
				if(null!=friends)
					friendList.add(friends);
			} catch (IllegalAccessException | InvocationTargetException e) {
				e.printStackTrace();
			}

		}
		PageVO pageVO = new PageVO(friendList, count, pageIndex, pageSize);
		
		return new PageVO(friendList,count, pageIndex, pageSize);
	}


	@SuppressWarnings("deprecation")
	@Override
	public List<Integer> queryFansId(int userId) {
		List<Integer> result = Lists.newArrayList();
		Document query = new Document("userId", userId);
		query.put("status",Friends.Status.Friends);
		query.put("isBeenBlack",0);
		query.put("blacklist",0);
		MongoCursor<Integer> iterator = getFriendsMongoCollection(userId).distinct("toUserId", query, Integer.class).iterator();
		while(iterator.hasNext()){
			result.add(iterator.next());
		}
		return result;
	}

	@Override
	public List<Friends> queryFollow(int userId,int status) {
		Document document = new Document("userId",userId).append("status", new Document(MongoOperator.NE,0));
		if(0 < status)
			document.append("status", status);
		List<Friends> friendList = new ArrayList<Friends>();
		MongoCursor<DBObject> iterator = getFriendsMongoCollection(userId).find(document).iterator();
		while(iterator.hasNext()){
			DBObject dbObject = iterator.next();
			 try {
				 Friends friends = DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
				 if(null!=friends)
					 friendList.add(friends);
			} catch (IllegalAccessException | InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return friendList;
	}
	

	public  Boolean queryFollowByToUserID(int userId,int toUserId)
	{
		Document document = new Document("userId",userId).append("toUserId",toUserId);
		MongoCursor<DBObject> iterator = getFriendsMongoCollection(userId).find(document).iterator();
		if(iterator.hasNext()) return true;
		return false;
	}
	/** @Description:（后台好友管理） 
	* @param userId
	* @param toUserId
	* @param status
	* @param page
	* @param limit
	* @return
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	**/
	public PageResult<Friends> consoleQueryFollow(int userId,int toUserId,int status,int page,int limit) throws IllegalAccessException, InvocationTargetException {
		MongoCollection<DBObject> collection = getFriendsMongoCollection(userId);
		PageResult<Friends> result = new PageResult<Friends>();
		/**
		 * 分库分表
		 */
		List<Friends> friendList = new ArrayList<Friends>();
		Document document = new Document("userId",userId).append("status",new Document(MongoOperator.NE,0)).append("toUserId",new Document(MongoOperator.GT,10100));
		if(0 < status)
			document.append("status",status);
		if(0 != toUserId)
			document.append("toUserId",toUserId);
		MongoCursor<DBObject> iterator = collection.find(document).skip((page-1)*limit).limit(limit).sort(new Document("createTime",-1)).iterator();
		while(iterator.hasNext()){
			DBObject dbObject = iterator.next();
			Friends friends = DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
			if(null!=friends)
			 friendList.add(friends);
		}

		result.setCount(collection.count(document));
		result.setData(friendList);

		return result;

	}
	

	public List<Friends> allFriendsInfo(int userId) {

		List<Friends> friendList = new ArrayList<Friends>();

		MongoCursor<DBObject> iterator = getFriendsMongoCollection(userId).find(new Document("userId",userId).append("toUserId", new Document(MongoOperator.NE,10000)).append("status", new Document(MongoOperator.NE,0))).iterator();
		try {
			while(iterator.hasNext()){
				DBObject dbObject = iterator.next();
				Friends friends =	DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
				friendList.add(friends);
			}
		}catch (Exception e) {
			e.printStackTrace();
		} finally {
			iterator.close();

		}
		return friendList;

	}

	@Override
	public List<Integer> queryFollowId(int userId) {

		List<Integer> result = Lists.newArrayList();
		MongoCursor<Integer> iterator = getFriendsMongoCollection(userId).distinct("toUserId", new Document("userId",userId).append("status", new Document(MongoOperator.NE,0)), Integer.class).iterator();
		try {
			while(iterator.hasNext()){
				result.add(iterator.next());
			}
		}catch (Exception e) {
			e.printStackTrace();
		} finally {
			iterator.close();
		}

		return result;
	}

	@Override
	public List<Friends> queryFriends(int userId) {
		/**
		 * 分库分表下的friends 数据
		 */
		List<Friends> friendList = new ArrayList<Friends>();
		MongoCursor<DBObject> iterator = getFriendsMongoCollection(userId).find(new Document("userId",userId).append("status", Friends.Status.Friends).append("blacklist", new Document(MongoOperator.NE,"1"))).iterator();

		while(iterator.hasNext()){
			DBObject dbObject = iterator.next();
			 try {
				 Friends friends = DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
				 if(null!=friends)
					 friendList.add(friends);
			} catch (IllegalAccessException | InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		return friendList;
	}
	
	@Override
	public List<Friends> friendsOrBlackList(int userId,String type) {
		/**
		 * 分库分表下的friends 数据
		 */
		Document document = new Document("userId",userId);

		if("friendList".equals(type)){  //返回好友和单向关注的用户列表
			document.append("status", new Document(MongoOperator.NE,Friends.Status.Stranger)).append("blacklist", new Document(MongoOperator.NE,Friends.Blacklist.Yes));
		}else if("blackList".equals(type)){ //返回黑名单的用户列表
			document.append("blacklist", Friends.Blacklist.Yes);
		}
		List<Friends> friendList = new ArrayList<Friends>();
		MongoCursor<DBObject> iterator = getFriendsMongoCollection(userId).find(document).iterator();

		try {
			while(iterator.hasNext()){
				DBObject dbObject = iterator.next();
				Friends friends;
				try {
					friends = DocumentToJavaBean.dbObject2Bean(dbObject, new Friends());
					friendList.add(friends);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		} finally {
			iterator.close();
		}
		return friendList;
	}



	@Override
	public Object saveFriends(Friends friends) {
		String chatRecordTimeOut=SKBeanUtils.getUserManager().getSettings(friends.getUserId()).getChatRecordTimeOut();
		friends.setChatRecordTimeOut(Double.valueOf(chatRecordTimeOut));
		DBObject friendsDbObj = objectToDBObject(friends);
		getFriendsMongoCollection(friends.getUserId()).insertOne(friendsDbObj);
		return friends;
	}

	@Override
	public Friends updateFriends(Friends friends) {
		MongoCollection<DBObject> friendsMongoCollection = getFriendsMongoCollection(friends.getUserId());

		/**
		 * 分库分表下修改friends 相关数据
		 */
		Document document = new Document("modifyTime", DateUtil.currentTimeSeconds());
		if (null != friends.getBlacklist()){
			document.append("blacklist", friends.getBlacklist());
		}
		if (null != friends.getIsBeenBlack()){
			document.append("isBeenBlack", friends.getIsBeenBlack());
		}
		if (null != friends.getStatus()){
			document.append("status", friends.getStatus());
		}
		if (!StringUtil.isEmpty(friends.getToNickname())){
			document.append("toNickname", friends.getToNickname());
		}
		if (!StringUtil.isEmpty(friends.getRemarkName())){
			document.append("remarkName", friends.getRemarkName());
		}
		if(0!=friends.getChatRecordTimeOut()){
			document.append("chatRecordTimeOut", friends.getChatRecordTimeOut());
		}

		if(null != friends.getToFriendsRole())
			document.append("toFriendsRole", friends.getToFriendsRole());
		if(0 != friends.getToUserType())
			document.append("toUserType", friends.getToUserType());
		if(0 != friends.getFromAddType())
			document.append("fromAddType", friends.getFromAddType());

		friendsMongoCollection.updateOne(new Document("userId",friends.getUserId()).append("toUserId", friends.getToUserId()), new Document(MongoOperator.SET,document));

		return getFriends(friends.getUserId(), friends.getToUserId());
	}


	public Friends updateFriendRemarkName(Integer userId,Integer toUserId,String remarkName,String describe) {

		MongoCollection<DBObject> collection = getFriendsMongoCollection(userId);
		Friends friends = getFriends(userId, toUserId);
		if (null == friends) {
			// 添加陌生人
			friends = new Friends();
			friends.setUserId(userId);
			friends.setToUserId(toUserId);
			friends.setRemarkName(remarkName);
			friends.setStatus(Friends.Status.Stranger);
			friends.setCreateTime(DateUtil.currentTimeSeconds());
			// 描述
			friends.setDescribe(describe);

			DBObject dbObj = objectToDBObject(friends);
			collection.insertOne(dbObj);
			return friends;
		} else {

			Document document = new Document("modifyTime", DateUtil.currentTimeSeconds());
			if (null == remarkName)
				document.append("remarkName", friends.getRemarkName());
			else
				document.append("remarkName", remarkName);
			// 描述
			document.append("describe", describe);
			MongoCollection<DBObject> friendsMongoCollection = getFriendsMongoCollection(friends.getUserId());
			friendsMongoCollection.updateOne(new Document("userId", friends.getUserId()).append("toUserId", friends.getToUserId()), new Document(MongoOperator.SET, document));
			// 维护reids好友数据
			SKBeanUtils.getRedisService().deleteFriends(userId);
			return getFriends(userId, toUserId);
		}
	}

	public void updateToFriendUserType(int toUserId,int userType,List<Integer> roles){
		List<String> collectionList = getCollectionList();
		 Document query=new Document("toUserId",toUserId);
		Document values=new Document(MongoOperator.SET,new Document("toFriendsRole", roles).append("toUserType", userType));
		collectionList.forEach(name->{
			getMongoCollection(name).updateMany(query,values);
		});
	}

	/**
	 *  更新与某个好友的消息加密方式
	 */
	@Override
	public  void updateFriendsEncryptType(int userId,int toUserId,byte type) {
		Document query=new Document("userId",userId);
		query.append("toUserId",toUserId);
		getCollection(userId).updateOne(query,new Document("$set",new Document("encryptType",type)));

	}
}
